/*******************************************************************
This file is part of iDialer.

iDialer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

iDialer is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with iDialer.  If not, see <http://www.gnu.org/licenses/>.
*******************************************************************/

#define EDB
#include <astdtapi.h>
#include <windows.h>
#include <windbase.h>
#include <tapi.h>
#include <tsp.h>
#include <pimstore.h>
#pragma comment(lib, "pimstore.lib")

#include "Macros.h"
#include "PhoneUtils.h"

#define TAPI_API_LOW_VERSION   0x00020000
#define TAPI_API_HIGH_VERSION  0x00020000

#define CAPS_BUFFER_SIZE    512

#define MAKEPROP(n,t)    ((n<<16)|CEVT_##t)
#define PROPID_SD_NAME		MAKEPROP(0x07, LPWSTR)
#define PROPID_SD_NUMBER	MAKEPROP(0x09, LPWSTR)
#define PROPID_SD_TYPE		MAKEPROP(0x04, I4)
#define PROPID_SD_KEY		MAKEPROP(0x02, I2)

#define DB_VOL_FN		TEXT("pim.vol")
#define SPEED_DB_NAME	TEXT("speed.db")

// http://blogs.msdn.com/windowsmobile/archive/2004/11/28/271110.aspx
HRESULT SHReadLineAddressCaps(LPTSTR szNumber, UINT cchNumber, PDWORD pdwCallFwdModes, UINT nLineNumber) {
    HRESULT  hr = E_FAIL;
    LRESULT  lResult = 0;
    HLINEAPP hLineApp;
    DWORD    dwNumDevs;
    DWORD    dwAPIVersion = TAPI_API_HIGH_VERSION;
    LINEINITIALIZEEXPARAMS liep;

    DWORD dwTAPILineDeviceID;
    const DWORD dwAddressID = nLineNumber - 1;

    liep.dwTotalSize = sizeof(liep);
    liep.dwOptions   = LINEINITIALIZEEXOPTION_USEEVENT;

    if (SUCCEEDED(lineInitializeEx(&hLineApp, 0, 0, TEXT("ExTapi_Lib"), &dwNumDevs, &dwAPIVersion, &liep)))
    {

        BYTE* pCapBuf = NULL;
        DWORD dwCapBufSize = CAPS_BUFFER_SIZE;
        LINEEXTENSIONID  LineExtensionID;
        LINEDEVCAPS*     pLineDevCaps = NULL;
        LINEADDRESSCAPS* placAddressCaps = NULL;

        pCapBuf = new BYTE[dwCapBufSize];
        CBR(pCapBuf);

        pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
        pLineDevCaps->dwTotalSize = dwCapBufSize;

        // Get TSP Line Device ID
        dwTAPILineDeviceID = 0xffffffff;
        for (DWORD dwCurrentDevID = 0 ; dwCurrentDevID < dwNumDevs ; dwCurrentDevID++)
        {
            if (0 == lineNegotiateAPIVersion(hLineApp, dwCurrentDevID, TAPI_API_LOW_VERSION, TAPI_API_HIGH_VERSION,
                &dwAPIVersion, &LineExtensionID))
            {
                lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);

                if (dwCapBufSize < pLineDevCaps->dwNeededSize)
                {
                    delete[] pCapBuf;
                    dwCapBufSize = pLineDevCaps->dwNeededSize;
                    pCapBuf = new BYTE[dwCapBufSize];
                    CBR(pCapBuf);

                    pLineDevCaps = (LINEDEVCAPS*)pCapBuf;
                    pLineDevCaps->dwTotalSize = dwCapBufSize;

                    lResult = lineGetDevCaps(hLineApp, dwCurrentDevID, dwAPIVersion, 0, pLineDevCaps);
                }

                if ((0 == lResult) &&
                    (0 == _tcscmp((TCHAR*)((BYTE*)pLineDevCaps+pLineDevCaps->dwLineNameOffset), CELLTSP_LINENAME_STRING)))
                {
                    dwTAPILineDeviceID = dwCurrentDevID;
                    break;
                }
            }
        }

        placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
        placAddressCaps->dwTotalSize = dwCapBufSize;

        lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);

        if (dwCapBufSize < placAddressCaps->dwNeededSize)
        {
            delete[] pCapBuf;
            dwCapBufSize = placAddressCaps->dwNeededSize;
            pCapBuf = new BYTE[dwCapBufSize];
            CBR(pCapBuf);

            placAddressCaps = (LINEADDRESSCAPS*)pCapBuf;
            placAddressCaps->dwTotalSize = dwCapBufSize;

            lResult = lineGetAddressCaps(hLineApp, dwTAPILineDeviceID, dwAddressID, dwAPIVersion, 0, placAddressCaps);
        }

        if (0 == lResult)
        {
            if (szNumber)
            {
                szNumber[0] = _T('\0');

                CBR(0 != placAddressCaps->dwAddressSize);

                // A non-zero dwAddressSize means a phone number was found
                ASSERT(0 != placAddressCaps->dwAddressOffset);
                PWCHAR tsAddress = (WCHAR*)(((BYTE*)placAddressCaps)+placAddressCaps->dwAddressOffset);

                StringCchCopy(szNumber, cchNumber, tsAddress);
            }

            // Record the allowed forwarding modes
            if (pdwCallFwdModes)
            {
                *pdwCallFwdModes = placAddressCaps->dwForwardModes;
            }

            hr = S_OK;
        }

        delete[] pCapBuf;
    } // End if ()

Error:
    lineShutdown(hLineApp);

    return hr;
}

// szNumber - Out Buffer for the phone number
//cchNumber - size of sznumber in characters
// nLineNumber - which phone line (1 or 2) to get the number for
HRESULT SHGetPhoneNumber(LPTSTR szNumber, UINT cchNumber, UINT nLineNumber) {
    return SHReadLineAddressCaps(szNumber, cchNumber, NULL, nLineNumber);
}


HRESULT ChoosePhoneNumber(TCHAR * szContactName, TCHAR * szPhoneNumber) {
    HRESULT hr                      = E_FAIL;    
    const CEPROPID c_propidAllVoice = PIMPR_ALL_VOICE; 
    CHOOSECONTACT cc                = {0};

    // Setup the CHOOSECONTACT structure.
    cc.cbSize                     = sizeof (cc);
    cc.hwndOwner                  = NULL;
    cc.dwFlags                    = CCF_RETURNCONTACTNAME | CCF_RETURNPROPERTYVALUE | CCF_HIDENEW;
    cc.lpstrTitle                 = TEXT("iDialer: Select a contact");
    cc.lpstrChoosePropertyText    = TEXT("Choose the phone number to dial...");
    cc.rgpropidRequiredProperties = &c_propidAllVoice;

    // The number of properties specified in the c_propidAllVoice array.
    cc.cRequiredProperties = 1;
    cc.hwndOwner           = NULL;

    // Display the Contact Chooser control, and prompt the user to choose a Contact.
    hr = ChooseContact(&cc);
    CHR(hr);

    StringCchCopy(szContactName, MAX_PATH, cc.bstrContactName);
    StringCchCopy(szPhoneNumber, MAX_PATH, cc.bstrPropertyValueSelected);

    // The name, and a string representation of the property, is returned according to the flags set in the CHOOSECONTACT structure above.
    //DEBUGMSG(TRUE, (L"%s's email address is %s", cc.bstrContactName, cc.bstrPropertyValueSelected));

Error:
    // Free memory.
    SysFreeString(cc.bstrContactName);
    SysFreeString(cc.bstrPropertyValueSelected);

    return hr;
}

void LoadSpeedDialInfo(SPEEDDIALINFO speedDialInfo[]) {
	HRESULT hr = E_FAIL;
	CEOIDINFOEX info = {0};

    CEGUID guid = {0};
    CEOID oid = 0;
    HANDLE hdb = NULL;

    CeMountDBVolEx(&guid, DB_VOL_FN, NULL, OPEN_EXISTING);

    hdb = CeOpenDatabaseInSession(NULL, &guid, &oid, SPEED_DB_NAME,
		NULL, CEDB_AUTOINCREMENT, NULL);

	CBR(hdb != INVALID_HANDLE_VALUE);

	TCHAR szName[TAPIMAXCALLEDPARTYSIZE] = {0};
	TCHAR szNumber[TAPIMAXDESTADDRESSSIZE] = {0};
	long lType = 0;
	short iKey = 0;

    CEPROPVAL * pRecord = NULL;
	DWORD  dwBufSize = 0;
    WORD   wNumProps;
    for (WORD iRec = 0; iRec < 5; iRec++) {
        oid = CeReadRecordPropsEx(hdb, CEDB_ALLOWREALLOC, &wNumProps, NULL,
			(LPBYTE *)&pRecord, &dwBufSize, NULL);
		
		if (!oid)
			break;
			
		lType = 0;
		iKey = 0;
		szName[0] = 0;
		szNumber[0] = 0;

		for (WORD i = 0; i < wNumProps; i++) {
			switch(pRecord[i].propid) {
				case PROPID_SD_NAME:
					StringCchCopy(szName, TAPIMAXCALLEDPARTYSIZE, pRecord[i].val.lpwstr);
					break;

				case PROPID_SD_NUMBER:
					StringCchCopy(szNumber, TAPIMAXDESTADDRESSSIZE, pRecord[i].val.lpwstr);
					break;

				case PROPID_SD_TYPE:
					lType = pRecord[i].val.lVal;
					break;
					
				case PROPID_SD_KEY:
					iKey = pRecord[i].val.iVal;
					break;
			}
		}

		if (lType != 1)
			continue;

		if (iKey >= 10)
			continue;
		
		StringCchCopy(speedDialInfo[iKey].name, TAPIMAXCALLEDPARTYSIZE, szName);
		StringCchCopy(speedDialInfo[iKey].number, TAPIMAXDESTADDRESSSIZE, szNumber);
    }

Error:
	LocalFree(pRecord);
    CloseHandle(hdb);


	return;
}

